package com.demo.crm.springboot3security.service.impl;

import static com.demo.crm.springboot3security.entity.table.Tables.CUSTOM_FORM;

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.demo.crm.springboot3security.dto.FormLayoutConfig;
import com.demo.crm.springboot3security.entity.CustomForm;
import com.demo.crm.springboot3security.entity.FormField;
import com.demo.crm.springboot3security.mapper.CustomFormMapper;
import com.demo.crm.springboot3security.service.FormLayoutService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mybatisflex.core.query.QueryWrapper;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 表单布局服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FormLayoutServiceImpl implements FormLayoutService {

    private final CustomFormMapper customFormMapper;
    private final ObjectMapper objectMapper;

    @Override
    @Transactional
    public CustomForm saveLayoutConfig(Long formId, FormLayoutConfig config) {
        CustomForm form = customFormMapper.selectOneWithFields(formId);

        // 验证布局配置
        if (!validateLayoutConfig(form, config)) {
            throw new RuntimeException("布局配置无效");
        }

        try {
            // 将布局配置转换为JSON字符串
            String layoutConfigJson = objectMapper.writeValueAsString(config);
            form.setLayoutConfig(layoutConfigJson);
            customFormMapper.update(form);
            return form;
        } catch (JsonProcessingException e) {
            log.error("布局配置序列化失败", e);
            throw new RuntimeException("布局配置保存失败");
        }
    }

    @Override
    public FormLayoutConfig getLayoutConfig(Long formId) {
        CustomForm form = customFormMapper.selectOneWithFields(formId);

        String layoutConfig = form.getLayoutConfig();
        if (layoutConfig == null || layoutConfig.isEmpty()) {
            return createDefaultLayout(form);
        }

        try {
            return objectMapper.readValue(layoutConfig, FormLayoutConfig.class);
        } catch (JsonProcessingException e) {
            log.error("布局配置解析失败", e);
            throw new RuntimeException("布局配置获取失败");
        }
    }

    @Override
    public boolean validateLayoutConfig(CustomForm form, FormLayoutConfig config) {
        if (config == null || config.getSections() == null || config.getSections().isEmpty()) {
            return false;
        }

        // 获取表单所有字段的编码集合
        Set<String> formFieldCodes = form.getFields().stream()
                .map(FormField::getCode)
                .collect(Collectors.toSet());

        // 获取布局中使用的所有字段编码
        Set<String> usedFieldCodes = new HashSet<>();
        for (FormLayoutConfig.Section section : config.getSections()) {
            if (section.getRows() == null)
                continue;

            for (FormLayoutConfig.Row row : section.getRows()) {
                if (row.getCells() == null)
                    continue;

                for (FormLayoutConfig.Cell cell : row.getCells()) {
                    if (cell.getFieldCode() != null) {
                        usedFieldCodes.add(cell.getFieldCode());
                    }
                }
            }
        }

        // 验证布局中使用的字段是否都存在于表单中
        return formFieldCodes.containsAll(usedFieldCodes);
    }

    /**
     * 创建默认布局配置
     * 将所有字段按顺序排列，每行一个字段
     */
    private FormLayoutConfig createDefaultLayout(CustomForm form) {
        FormLayoutConfig config = new FormLayoutConfig();
        FormLayoutConfig.Section section = new FormLayoutConfig.Section();
        section.setId("default");
        section.setTitle("基本信息");
        section.setColumns(1);
        section.setRows(form.getFields().stream()
                .map(field -> {
                    FormLayoutConfig.Row row = new FormLayoutConfig.Row();
                    row.setId("row_" + field.getCode());

                    FormLayoutConfig.Cell cell = new FormLayoutConfig.Cell();
                    cell.setId("cell_" + field.getCode());
                    cell.setFieldCode(field.getCode());
                    cell.setColspan(1);
                    cell.setRowspan(1);

                    row.setCells(java.util.Collections.singletonList(cell));
                    return row;
                })
                .collect(Collectors.toList()));

        config.setSections(java.util.Collections.singletonList(section));
        return config;
    }

    @Override
    public CustomForm getFormLayout(String code) {
        return customFormMapper.selectOneByQuery(QueryWrapper.create().where(CUSTOM_FORM.CODE.eq(code)));
    }
}